package cn.xawl.interview.thread;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @author lh
 * @date 2020/08/24 19:29:57
 *
 * ABA问题的解决：AtomicStampedReference
 *
 *  true代表修改成功，false代表修改失败
 *
 *
 **/
public class ABADemo {
    static AtomicInteger atomicInteger = new AtomicInteger(100);
    //AtomicStampedReference构造器需要提供初始值和初始stamp
    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);
    public static void main(String[] args) {

        System.out.println("============ABA问题===============");

        new Thread(() -> {
            //休眠3秒，保证t2线程能完成ABA
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() +"\t开始修改" + atomicInteger.compareAndSet(100, 2020) + "\t实际值" + atomicInteger.get());

        }, "t1").start();

        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t第一次修改：" + atomicInteger.compareAndSet(100, 101) + "\t" + atomicInteger.get());
            System.out.println(Thread.currentThread().getName() + "\t第二次修改：" + atomicInteger.compareAndSet(101, 100) + "\t" + atomicInteger.get());
        }, "t2").start();

        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("============ABA问题的解决===============");




        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();//过去获取当前stamp
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print(Thread.currentThread().getName() +"\t开始修改：" + atomicStampedReference.compareAndSet(100, 2020, stamp, stamp + 1) + "\t实际值" + atomicStampedReference.getReference());
            System.out.println("\t当前版本号：" + atomicStampedReference.getStamp());
        }, "t3").start();

        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();//过去获取当前stamp
            System.out.println("未修改之前，stamp：" + stamp);
            //休眠1秒，保证t3可以拿到stamp
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.print(Thread.currentThread().getName() + "\t第一次修改：" + atomicStampedReference.compareAndSet(100, 101, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1) + "\t" + atomicStampedReference.getReference());
            System.out.println("\t当前版本号：" + atomicStampedReference.getStamp());
            System.out.print(Thread.currentThread().getName() + "\t第二次修改：" + atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1) + "\t" + atomicStampedReference.getReference());
            System.out.println("\t当前版本号：" + atomicStampedReference.getStamp());
        }, "t4").start();


    }

}
